﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace ShowCat
{
    class KeyBoardHook
    {
        private const int WH_KEYBOARD_LL = 13; 
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_KEYUP = 0x0101;

        private delegate int HookHandle(int nCode, int wParam, IntPtr lParam);
        private static HookHandle _keyBoardHookProcedure;
        public delegate void ProcessKeyHandle(HookStruct param, out bool handle);
        private static ProcessKeyHandle _clientMethod = null;
        private static int _hHookValue = 0;

        [StructLayout(LayoutKind.Sequential)]
        public class HookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnhookWindowsHookEx(int idHook);
        [DllImport("user32.dll")]
        private static extern int SetWindowsHookEx(int intHook, HookHandle lpfn, IntPtr hInstance,int threa);
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(String name);
        [DllImport("user32.dll")]
        public static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
        private IntPtr _hookWindowPtr = IntPtr.Zero;


        public void InstallHook(ProcessKeyHandle clientMethod)
        {
            //客户端委托事件 
            _clientMethod = clientMethod;
            //安装键盘钩子
            if (_hHookValue == 0)
            {
                _keyBoardHookProcedure = new HookHandle(GetHookProc);
                _hookWindowPtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
                _hHookValue = SetWindowsHookEx(
                    WH_KEYBOARD_LL,
                    _keyBoardHookProcedure,
                    _hookWindowPtr,
                    0
                    );
                if (_hHookValue == 0)
                {
                    //设置钩子失败
                    UninstallHook();
                }
            }
        }

        public void UninstallHook()
        {
            if (_hHookValue != 0)
            {
                bool ret = UnhookWindowsHookEx(_hHookValue);
                if (ret)
                {
                    _hHookValue = 0;
                }
            }
        }
        private static int GetHookProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode >= 0 && (wParam == WM_KEYDOWN) || (wParam == WM_KEYUP))
            {
               
                HookStruct hookStruc = (HookStruct)Marshal.PtrToStructure(lParam, typeof(HookStruct));
                hookStruc.dwExtraInfo = wParam;
                bool handle = false;
                
                _clientMethod(hookStruc, out handle);
                handle = false;

                if (handle) { return 1; }
            }
            return CallNextHookEx(_hHookValue, nCode, wParam, lParam);
        }
    }
}
